package cn.dansj.controller;

import cn.dansj.common.redis.annotation.lock.Lock4j;
import cn.dansj.common.request.annotation.http.GetMethod;
import cn.dansj.common.request.annotation.http.PostMethod;
import cn.dansj.common.request.annotation.http.RequestMappingMethod;
import cn.dansj.common.request.annotation.http.RequestParam;
import cn.dansj.common.utils.json.DictMap;
import cn.dansj.entity.RequestLog;
import cn.dansj.common.utils.enums.BooleanType;
import cn.dansj.service.RequestLogService;
import cn.dansj.entity.Setting;
import cn.dansj.enums.GlobalEnv;
import cn.dansj.service.SettingService;
import cn.dansj.common.utils.transfer.DateTime;
import cn.dansj.common.utils.transfer.Verification;
import cn.dansj.common.utils.bean.Return;
import cn.dansj.common.utils.transfer.RandomUtils;
import cn.dansj.utils.project.ProjectUtils;
import cn.dansj.common.redis.RedisUtils;
import org.springframework.data.domain.Page;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RequestMappingMethod("/system")
public class SystemController {
    private final SettingService settingService;
    private final RedisUtils redisUtils;
    private final RequestLogService requestLogService;

    public SystemController(SettingService settingService, RedisUtils redisUtils, RequestLogService requestLogService) {
        this.settingService = settingService;
        this.redisUtils = redisUtils;
        this.requestLogService = requestLogService;
    }

    //设置获取标题
    @GetMethod("/title")
    public Return<?> getTitle() {
        return Return.T(settingService.getTitle());
    }

    //根据标题获取内容
    @GetMethod("/content")
    public Return<?> content(String title) {
        return Return.T(settingService.getAllByClassCode(title));
    }

    @GetMethod("/getSetting")
    public Return<?> getSetting(String classCode, String name) {
        if (Verification.checkNull(classCode)) return Return.T(false, "classCode参数不能为空");
        DictMap settings = ProjectUtils.getSettingByRedis(classCode);
        if (Verification.checkNotNull(name)) return Return.T(settings.get(name));
        return Return.T(settings);
    }

    /*
     * 保存配置
     * */
    @PostMethod("/modify")
    @Lock4j
    public Return<?> modify(@RequestParam DictMap request) {
        String sequence = request.getString("sequence");
        if (Verification.checkNotNull(sequence)) {
            Setting setting = settingService.getBySequence(sequence);
            if (setting == null) return Return.T(false, "配置信息不存在");
            setting.setValue(request.getString("value"));
            setting.setValueType(request.getIntValue("valueType"));
            setting.setRemark(request.getString("remark"));

            settingService.save(setting);
            GlobalEnv.threadPool.execute(() -> reCacheSystemSettingToRedis(setting.getClassCode()));
            return Return.T(true, "字典更新成功");
        } else {
            Setting setting = new Setting();
            int valueType = request.getIntValue("valueType");
            String classCode = request.getString("classCode");
            String name = request.getString("name");
            int count = settingService.countByClassCodeAndName(classCode, name);
            if (count > 0) return Return.T(false, "该类型和名称下,字典已存在");
            setting.setSequence(RandomUtils.sequence());
            setting.setClassCode(classCode);
            setting.setName(name);
            setting.setValue(valueType == 1 ? request.getString("inputValue") : request.getString("selectValue"));
            setting.setValueType(valueType);
            setting.setRemark(request.getString("remark"));
            setting.setRn(settingService.getMaxRN(classCode) + 1);
            settingService.save(setting);
            GlobalEnv.threadPool.execute(() -> reCacheSystemSettingToRedis(setting.getClassCode()));
            return Return.T(true, "字典添加成功");
        }
    }

    @PostMethod("/updateSort")
    public Return<?> updateSort(@RequestParam DictMap jsonObject) {
        settingService.updateSort(DictMap.parseObject(jsonObject.get("data"), new DictMap.JavaType<>() {
        }));
        GlobalEnv.threadPool.execute(() -> reCacheSystemSettingToRedis(jsonObject.getString("classCode")));
        return Return.T(true, "排序更新成功");
    }

    @PostMethod("updateSetting")
    public Return<?> updateSetting(@RequestParam String classCode, @RequestParam String name, @RequestParam String value) {
        final Setting setting = settingService.getByClassCodeAndName(classCode, name);
        if (setting == null) return Return.T(false, "配置项不存在");
        setting.setValue(value);
        settingService.save(setting);
        GlobalEnv.threadPool.execute(() -> reCacheSystemSettingToRedis(classCode));
        return Return.T(true, "保存成功");
    }

    @GetMethod(value = "/log", nologging = BooleanType.TRUE)
    public Return<?> getLog(@RequestParam("search") DictMap search, @RequestParam int page, @RequestParam int limit) {
        String url = search.getString("url");
        int status = Verification.checkNotNull(search.getString("status")) ? search.getIntValue("status") : -1;
        long cost = search.getLongValue("cost");
        String date = search.getString("date");
        Page<RequestLog> requestLogs = requestLogService.search(page, limit, url, status, cost, date, null, "", -1);
        return Return.T(requestLogs.getContent()).setTotalRecord(requestLogs.getTotalElements());
    }

    @PostMethod("/cache")
    public Return<?> cache() {
        final List<Setting> allSetting = settingService.getAll();
        Map<String, List<Setting>> cache = new HashMap<>();
        for (Setting setting : allSetting) {
            List<Setting> settings = cache.get(setting.getClassCode());
            if (settings == null) settings = new ArrayList<>();
            settings.add(setting);
            cache.put(setting.getClassCode(), settings);
        }
        redisUtils.deleteByPrefix("system.setting@*");
        for (String classCode : cache.keySet()) {
            redisUtils.hmset("system.setting@" + classCode, DictMap.of("cache", cache.get(classCode), "date", DateTime.getInstance().stringTimestamp()));
        }
        return Return.T(true, "共执行" + cache.size() + "类" + allSetting.size() + "项字典缓存数据");
    }

    private void reCacheSystemSettingToRedis(String classCode) {
        List<Setting> settings = settingService.getAllByClassCode(classCode);
        redisUtils.hmset("system.setting@" + classCode, DictMap.of("cache", settings, "date", DateTime.getInstance().stringTimestamp()));
    }
}
